#include "math/mathconsts.h"
#include "math/mathfuncs.h"
#include "math/quaternion.h"
#include "math/vector3.h"
#include "math/matrix4x4.h"
#include "math/vectorn.h"
#include "math/matrixmxn.h"
#include "math/line.h"
#include "math/types.h"

#include "camera_ctrl.h"

CameraCtrl::CameraCtrl() :
m_rbtn_down(false),
m_mouse_pos_down(0, 0),
m_cam_to_origin_down(0),
m_cam_rot_mat_down(0),
m_cam_to_origin(0)
{

}

void CameraCtrl::InitCamera(const nieIK::Vector3 &pos,
							const nieIK::Vector3 &forward, 
							const nieIK::Vector3 &up)
{
	nieIK::Matrix4x4 rot(0);
	MakeMatOrient(rot, forward, up);
	m_camera_data.Init(pos, rot);
	m_cam_to_origin = -m_camera_data.m_pos;

}

void CameraCtrl::OnRbuttonDown(int x, int y)
{
	m_rbtn_down = true;
	m_mouse_pos_down.x = (Float)x;
	m_mouse_pos_down.y = (Float)y;
	m_cam_to_origin_down = -m_camera_data.m_pos;
	m_cam_rot_mat_down = m_camera_data.m_rot;
}

void CameraCtrl::OnRbuttonUp(int x, int y)
{
	m_rbtn_down = false;
}

void CameraCtrl::OnMouseMove(int x, int y)
{
	if (m_rbtn_down)
	{
		MouseRotateCamera(x, y);
	}
}

void CameraCtrl::OnMouseWheel(short zDelta)
{
	if (zDelta != 0)
	{
		m_cam_to_origin *= 1.0f - 0.0016f * zDelta;
		m_camera_data.m_pos = -m_cam_to_origin;
		m_cam_to_origin = -m_camera_data.m_pos;
	}
}

const nieIK::Matrix4x4& CameraCtrl::GetCameraRot() const
{
	return m_camera_data.m_rot;
}

const nieIK::Vector3& CameraCtrl::GetCameraPos() const
{
	return m_camera_data.m_pos;
}

void CameraCtrl::MouseRotateCamera(int x, int y)
{
	nieIK::Vector3 p0(m_mouse_pos_down.x, m_mouse_pos_down.y, 0.0f);
	nieIK::Vector3 p1((Float)x, (Float)y, 0.0f);
	p1 -= p0;
	if (p1.IsZero())
	{
		return;
	}

	nieIK::Vector3(0);
	nieIK::Line axis;
	axis.p0 = nieIK::Vector3(0);

	m_camera_data.m_rot.Set3X3(m_cam_rot_mat_down);
	m_camera_data.m_pos = -m_cam_to_origin_down;

	m_camera_data.m_rot.GetRight(axis.dir);
	
	m_camera_data.RotateAxis(axis, p1.y * 0.012f);
	axis.dir.Set(0.0f, 0.0f, 1.0f);
	m_camera_data.RotateAxis(axis, p1.x * 0.012f);

	m_cam_to_origin = -m_camera_data.m_pos;

}
